<template>
  <grid title="请求日志记录">
    <el-form inline
             style="width: 100%; text-align: left"
             label-width="60px"
             @submit.native.prevent="onSubmit"
             @reset.native.prevent="onReset"
             size="small">
      <el-col :md="24">
        <el-form-item label="用户名">
          <el-input v-model="query.name"
                    placeholder="请输入用户名(完全匹配)"
                    clearable></el-input>
        </el-form-item>
        <el-form-item label="用户ID">
          <el-input v-model="query.user_id"
                    placeholder="请输入用户id"
                    clearable></el-input>
        </el-form-item>
        <el-form-item label="请求方式"
                      label-width="80px">
          <el-select v-model="query.method">
            <el-option label="GET"
                       value="GET"></el-option>
            <el-option label="POST"
                       value="POST"></el-option>
            <el-option label="PUT"
                       value="PUT"></el-option>
            <el-option label="DELETE"
                       value="DELETE"></el-option>
          </el-select>
        </el-form-item>

        <el-form-item label="请求地址"
                      label-width="75px">
          <el-input v-model="query.path"
                    placeholder="例: api/v1/items"
                    clearable></el-input>
        </el-form-item>
      </el-col>
      <el-col :md="24">
        <el-form-item label="IP">
          <el-input v-model="query.ip"
                    placeholder="例: 192.168.1.1"
                    clearable></el-input>
        </el-form-item>
        <el-form-item label="请求时间"
                      label-width="80px">
          <el-date-picker v-model="query.start_time"
                          class="modify-input"
                          type="datetime"
                          size="mini"
                          value-format="yyyy-MM-dd HH:mm:ss"
                          placeholder="选择开始日期">
          </el-date-picker>
          -
          <el-date-picker v-model="query.end_time"
                          class="modify-input"
                          type="datetime"
                          size="mini"
                          value-format="yyyy-MM-dd HH:mm:ss"
                          placeholder="选择结束日期">
          </el-date-picker>
        </el-form-item>
        <el-form-item>
          <el-button type="primary"
                     native-type="submit">筛选</el-button>
          <el-button native-type="reset">重置</el-button>
        </el-form-item>
      </el-col>
    </el-form>
    <el-table :data="request_list"
              border
              :resizable="false"
              stripe>
      <el-table-column type="expand">
        <template slot-scope="props">
          <div class="flex-pre"
               v-if="props.row.user_agent">请求设备：{{ props.row.user_agent }}</div>
        </template>
      </el-table-column>
      <el-table-column prop="time"
                       label="发生时间">
        <template slot-scope="scope">
          {{scope.row.time | timeFilter }}
        </template>
      </el-table-column>
      <el-table-column prop="user"
                       label="用户"
                       width="130px">
        <template slot-scope="scope">
          <user-popover v-if="scope.row.user"
                        :user="scope.row.user"
                        :nameRequire="true"></user-popover>
          <el-tag v-else>游客</el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="ip"
                       label="ip地址">
      </el-table-column>
      <el-table-column prop="module"
                       label="请求方法"
                       width="300"
                       show-overflow-tooltip>
      </el-table-column>
      <el-table-column prop="method"
                       width="80"
                       align="center"
                       label="请求方式">
        <template slot-scope="scope">
          <el-tag size="small"
                  v-if="scope.row.method === 'GET'">{{scope.row.method}}</el-tag>
          <el-tag size="small"
                  type="success"
                  v-else-if="scope.row.method === 'POST'">{{scope.row.method}}</el-tag>
          <el-tag size="small"
                  type="danger"
                  v-else-if="scope.row.method === 'DELETE'">{{scope.row.method}}</el-tag>
          <el-tag size="small"
                  type="warning"
                  v-else-if="scope.row.method === 'PUT'">{{scope.row.method}}</el-tag>
          <el-tag size="small"
                  type="info"
                  v-else>{{scope.row.method}}</el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="router"
                       label="路由"
                       show-overflow-tooltip>
      </el-table-column>
      <el-table-column prop="exec_time"
                       label="执行时间">
        <template slot-scope="scope">
          {{(scope.row.exec_time/1000).toFixed(4)}}s
        </template>
      </el-table-column>
      <el-table-column prop="status"
                       label="返回状态">
        <template slot-scope="scope">
          <el-tag size="small"
                  :type="obtainTagType(scope.row.status)">{{scope.row.status | responseStatusFilter}}</el-tag>
        </template>
      </el-table-column>
      <el-table-column fixed="right"
                       label="操作"
                       width="240">
        <template slot-scope="scope">
          <el-button type="primary"
                     size="small"
                     @click="editRow(scope.row.id)">详情</el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination layout="total, prev, pager, next"
                   background
                   @current-change="fetch"
                   :current-page.sync="query.page"
                   :page-size="query.limit"
                   hide-on-single-page
                   style="display: flex;justify-content: center;"
                   :total="request_total">
    </el-pagination>

    <el-drawer :title="title"
               :visible.sync="drawerVisible"
               direction="rtl"
               destroy-on-close>
      <el-card class="box-card"
               shadow="never"
               body-style="background-color: #f6f6f6;padding:0">
        <div slot="header"
             class="clearfix">
          <span>客户端</span>
        </div>
        <div class="j-draw-table-class">
          <div class="j-normal-item j-draw-middle-item">发生时间：{{form.time | timeFilter}}</div>
          <div class="j-normal-item j-draw-middle-item">访问IP：{{form.ip}}</div>
        </div>
        <div class="j-draw-table-class"
             v-if="form.browser">
          <div class="j-normal-item j-draw-middle-item">终端设备：{{form.browser.terminal}}</div>
          <div class="j-normal-item j-draw-middle-item">浏览器：{{form.browser.browser}}</div>
        </div>
        <div class="j-draw-table-class">
          <div class="j-normal-item">{{form.user_agent}}</div>
        </div>
      </el-card>
      <el-card class="box-card"
               shadow="never"
               body-style="background-color: #f6f6f6;padding:0">
        <div slot="header"
             class="clearfix">
          <span>请求</span>
        </div>
        <div class="j-draw-table-class">
          <div class="j-normal-item j-draw-middle-item">用户名：
            <template v-if="form.user">
              <div style="display:inline-black">
                <user-popover :user="form.user"
                              :nameRequire="true"></user-popover>
              </div>
            </template>
            <template v-else>
              <el-tag size="mini">游客</el-tag>
            </template>
          </div>
          <div class="j-normal-item j-draw-middle-item">路由：<el-tag size="mini">{{form.method}}</el-tag>
            <font style="margin-left: 5px">{{form.router}}</font>
          </div>
        </div>
        <div class="j-draw-table-class">
          <div class="j-normal-item j-draw-left-item">模块：</div>
          <div class="j-normal-item j-draw-right-item">
            <el-tag type="success">{{form.module}}</el-tag>
          </div>
        </div>
        <div class="j-draw-table-class">
          <div class="j-normal-item"
               style="width: 100%">
            <p style="margin-top: 0;">请求头：</p>
            <div v-for="(header,index) in form.header"
                 :key="index"
                 style="max-width: 100%;word-break: break-all;">
              {{index | upperFirst}}：{{header | stitchingHeader}}
            </div>
          </div>
        </div>
        <div class="j-draw-table-class">
          <div class="j-normal-item"
               style="padding-top:0;width:100%">
            <p>请求参数：</p>
            <pre class="j-code"
                 style="overflow: auto"
                 v-html="form.body_params"></pre>
          </div>
        </div>
      </el-card>
      <el-card class="box-card"
               shadow="never"
               body-style="background-color: #f6f6f6;padding:0">
        <div slot="header"
             class="clearfix">
          <span>运行</span>
        </div>
        <div class="j-draw-table-class"
             v-if="form.status < 500">
          <div class="j-normal-item j-draw-left-item">异常：</div>
          <div class="j-normal-item j-draw-right-item">null</div>
        </div>
        <div class="j-draw-table-class"
             v-else>
          <div class="j-normal-item"
               style="padding-top:0;width:100%">
            <p>异常：</p>
            <pre class="j-code"
                 v-html="form.response"></pre>
          </div>
        </div>
      </el-card>
      <el-card class="box-card"
               shadow="never"
               body-style="background-color: #f6f6f6;padding:0">
        <div slot="header"
             class="clearfix">
          <span>响应</span>
        </div>
        <div class="j-draw-table-class">
          <div class="j-normal-item j-draw-middle-item">执行状态：<el-tag size="small"
                    :type="obtainTagType(form.status)">{{form.status | responseStatusFilter}}</el-tag>
          </div>
          <div class="j-normal-item j-draw-middle-item">执行时间：{{(form.exec_time/1000).toFixed(4)}}s</div>
        </div>
        <div class="j-draw-table-class"
             v-if="form.status < 500">
          <div class="j-normal-item"
               style="padding-top:0;width:100%">
            <p>返回信息：</p>
            <pre class="j-code"
                 v-html="form.response"></pre>
          </div>
        </div>
        <div class="j-draw-table-class"
             v-else>
          <div class="j-normal-item j-draw-left-item">返回信息：</div>
          <div class="j-normal-item j-draw-right-item">null</div>
        </div>
      </el-card>
    </el-drawer>
  </grid>
</template>

<script>
import { mapActions, mapGetters } from 'vuex'
import listMixin from '@/mixin/list'
import { responseStatusFilter } from '@/utils/filters'
import { fetchRequestView as fetchView } from './api'
import { jsonHighlight } from '@/utils/json'
import { judgeTerminalBrowser } from '@/utils/browser'
import userPopover from '@/components/common/user-popover'

export default {
  title: '请求日志记录',
  data () {
    return {
      query: {
        limit: 12,
        page: 1,
        name: undefined,
        user_id: undefined,
        path: undefined,
        ip: undefined,
        method: undefined,
        start_time: undefined,
        end_time: undefined
      },
      form: {},
      formDefault: {
        id: undefined,
        time: undefined,
        method: undefined,
        ip: undefined,
        user_agent: undefined,
        user: undefined,
        module: undefined,
        body_params: undefined,
        header: undefined,
        router: undefined,
        status: undefined,
        exec_time: undefined,
        response: undefined,
        browser: {}
      },
      drawerVisible: false,
      title: undefined
    }
  },
  mixins: [listMixin],
  filters: {
    responseStatusFilter,
    stitchingHeader (array) {
      if (typeof array !== 'object') {
        return array
      }
      return array.join('\\n')
    },
    upperFirst (string) {
      return string.charAt(0).toUpperCase() + string.slice(1)
    }
  },
  components: {
    userPopover
  },
  async asyncData ({ store, route }) {
    const { query } = route;
    return store.dispatch('log/fetchRequestList', { page: 1, limit: 12 })
  },
  computed: {
    ...mapGetters('log', ['request_list', 'request_total'])
  },
  methods: {
    ...mapActions('log', ['fetchRequestList']),
    obtainTagType (status) {
      if (status < 200) {
        return 'info'
      } else if (status < 300) {
        return 'success'
      } else if (status < 400) {
        return ''
      } else if (status < 500) {
        return 'warning'
      } else {
        return 'danger'
      }
    },
    fetchList (params) {
      return this.fetchRequestList(params)
    },
    fetch () {
      this.fetchRequestList(this.query)
    },
    async editRow (id) {
      await fetchView(id).then(({ data: { data } }) => {
        this.form = this.filterForm(data)
        this.form.response = jsonHighlight(JSON.parse(this.form.response))
        this.form.body_params = jsonHighlight(JSON.parse(this.form.body_params))
        this.form.browser = judgeTerminalBrowser(this.form.user_agent)
      })
      this.title = `日志详情（id：${id}）`
      this.drawerVisible = true
    }
  }
}
</script>

<style lang="scss" scoped>
.box-card {
  margin: 0;
  border: none;
}
.j-draw-table-class {
  font-size: 13px;
  display: flex;
  align-items: center;
  border-top: 1px solid #bbb;
  &:last-child {
    border-bottom: 1px solid #bbb;
  }
  div.j-normal-item {
    box-sizing: border-box;
    padding: 12px 15px;
    display: inline-block;
  }
  div.j-draw-middle-item {
    width: 50%;
    display: flex;
    align-items: center;
    &:nth-child(2n) {
      border-left: 1px solid #bbb;
    }
  }
  div.j-draw-left-item {
    padding: 12px 0 12px 12px;
  }
  div.j-draw-right-item {
    padding: 12px 0;
  }
}
</style>
